package com.neusoft.neuiotms.dcom.service.hn.impl;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import org.activiti.editor.language.json.converter.util.CollectionUtils;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.neusoft.bizcore.auth.common.bean.RoleBean;
import com.neusoft.bizcore.auth.common.bean.UserBean;
import com.neusoft.bizcore.schedule.service.JobMgrService;
import com.neusoft.bizcore.web.constant.ExceptionConstants;
import com.neusoft.bizcore.web.exception.UnitedException;
import com.neusoft.bizcore.web.support.Searchable;
import com.neusoft.neuiotms.common.dto.DictionaryDTO;
import com.neusoft.neuiotms.common.service.DictionaryService;
import com.neusoft.neuiotms.dcom.constants.DCOMConstants;
import com.neusoft.neuiotms.dcom.converter.hn.HnInspectionPlanConverter;
import com.neusoft.neuiotms.dcom.dto.hn.HnInspectionPlanDTO;
import com.neusoft.neuiotms.dcom.model.hn.HnInspectionPlan;
import com.neusoft.neuiotms.dcom.repository.hn.HnInspectionPlanRepository;
import com.neusoft.neuiotms.dcom.service.hn.HnInspectionPlanService;
import com.neusoft.neuiotms.dcom.task.hn.HnInspectionTaskJob;
import com.neusoft.neuiotms.dcom.util.PermUtils;

@Service
public class HnInspectionPlanServiceImpl implements HnInspectionPlanService {

    @Autowired
    private HnInspectionPlanRepository hnInspectionPlanRepository;

    @Autowired
    private HnInspectionPlanConverter hnInspectionPlanConverter;

    @Autowired
    private DictionaryService dictionaryService;

    @Autowired
    private JobMgrService jobMgrService;

    @Override
    public List<HnInspectionPlanDTO> index(final Searchable searchable) {
        final List<HnInspectionPlan> model = this.hnInspectionPlanRepository.index(searchable);
        return this.hnInspectionPlanConverter.toListDTO(model);
    }

    @Override
    public Page<HnInspectionPlanDTO> search(final Pageable pageable, final Searchable searchable, final UserBean user) {
        //查找未做删除标记的
        searchable.put("delFlag", false);
        if (PermUtils.isWorkerGroupLeader(user)) {
            searchable.put("userCode", user.getUsername());
        }
        final Page<HnInspectionPlan> page = this.hnInspectionPlanRepository.search(pageable, searchable);
        return this.hnInspectionPlanConverter.toPageDTO(page);
    }

    @Override
    public HnInspectionPlanDTO create(final HnInspectionPlanDTO dto, final UserBean user) {
        //        final List<HnInspectionPlan> check =
        //                this.hnInspectionPlanRepository.findByInstitutionCodeAndDelFlagAndDisabled(dto.getInstitutionCode(),
        //                        false, false);
        //        if (CollectionUtils.isNotEmpty(check) && !dto.isDisabled()) {
        //            throw new UnitedException("一个厅局只能创建1个正在运行的巡检计划");
        //        }
        if (user == null) {
            throw new UnitedException("创建巡检计划当前用户不能为空");
        }
        final List<String> roles = user.getRoles().stream().map(RoleBean::getRole).collect(Collectors.toList());
        if (!roles.contains(DCOMConstants.WORKER_GROUP_LEADER)) {
            throw new UnitedException("只有一线运维组长可以创建巡检计划");
        }
        final List<DictionaryDTO> dictionary =
                this.dictionaryService.findByDictionaryType(DCOMConstants.HN_INSPECTION_DAY_CRON_TIME);
        dto.setCronTime(dictionary.get(0).getText());
        dto.setUserCode(user.getUsername());
        dto.setUserName(user.getName());

        final HnInspectionPlan plan = this.hnInspectionPlanRepository.save(this.hnInspectionPlanConverter.toModel(dto));
        //        this.addInspectionScheduleJob(plan);
        return this.hnInspectionPlanConverter.toDTO(plan);
    }

    @Override
    @Transactional
    public HnInspectionPlanDTO update(final Long id, final HnInspectionPlanDTO dto, final UserBean user) {
        final HnInspectionPlan check = this.hnInspectionPlanRepository.getOne(id);
        if (check == null) {
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND, new Object[] {id });
        }
        //        final List<HnInspectionPlan> plans =
        //                this.hnInspectionPlanRepository.findByInstitutionCodeAndDelFlagAndDisabled(dto.getInstitutionCode(),
        //                        false, false);
        //        if (CollectionUtils.isNotEmpty(plans) && (plans.get(0).getId().longValue() != dto.getId().longValue())
        //                && !dto.isDisabled()) {
        //            throw new UnitedException("一个厅局只能创建1个正在运行的巡检计划");
        //        }
        if (user == null) {
            throw new UnitedException("更新巡检计划当前用户不能为空");
        }
        final List<String> roles = user.getRoles().stream().map(RoleBean::getRole).collect(Collectors.toList());
        if (!roles.contains(DCOMConstants.WORKER_GROUP_LEADER)) {
            throw new UnitedException("只有一线运维组长可以创建巡检计划");
        }

        //当前版本已经关联了任务,生成新的版本
        if (CollectionUtils.isNotEmpty(check.getTask())) {
            dto.setId(null);
            int ver = dto.getVersion();
            dto.setVersion(++ver);
            //将当前版本置为删除，并且禁用
            check.setDisabled(true);
            check.setDelFlag(true);
            this.hnInspectionPlanRepository.save(check);
        }

        dto.setUserCode(user.getUsername());
        dto.setUserName(user.getName());
        dto.setUpdateTime(new Date());
        final HnInspectionPlan plan = this.hnInspectionPlanRepository.save(this.hnInspectionPlanConverter.toModel(dto));
        //        this.addInspectionScheduleJob(plan);
        return this.hnInspectionPlanConverter.toDTO(plan);
    }

    @Override
    public HnInspectionPlanDTO details(final Long id) {
        final HnInspectionPlan check = this.hnInspectionPlanRepository.getOne(id);
        if (check == null) {
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND, new Object[] {id });
        }
        return this.hnInspectionPlanConverter.toDTO(check);
    }

    @Override
    public void delete(final Long id) {
        final HnInspectionPlan check = this.hnInspectionPlanRepository.getOne(id);
        if (check == null) {
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND, new Object[] {id });
        }
        if (CollectionUtils.isNotEmpty(check.getTask())) {
            throw new UnitedException("已经生成巡检任务，不允许删除");
        }
        this.jobMgrService.pauseJob(check.getCode());
        this.jobMgrService.deleteJob(check.getCode());
        this.hnInspectionPlanRepository.deleteById(id);
    }

    private void addInspectionScheduleJob(final HnInspectionPlan model) {
        this.jobMgrService.pauseJob(model.getCode());
        this.jobMgrService.deleteJob(model.getCode());
        if (!model.isDisabled()) {
            final JobDetail jobDetail = JobBuilder
                    .newJob((HnInspectionTaskJob.class))
                    .withIdentity(model.getCode())
                    .withDescription("每日巡检任务生成：" + model.getInstitutionName())
                    .build();
            jobDetail.getJobDataMap().put("hnInspectionRuleId", model.getId());
            this.jobMgrService.scheduleCronJob(model.getCode(), model.getCronTime(), jobDetail);
        }
    }

    @Override
    public void enable(final Long id) {

        final HnInspectionPlan plan = this.hnInspectionPlanRepository.getOne(id);
        if (plan == null) {
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND, new Object[] {id });
        }
        final List<HnInspectionPlan> plans =
                this.hnInspectionPlanRepository.findByInstitutionCodeAndDelFlagAndDisabled(plan.getInstitutionCode(),
                        false, false);
        if (CollectionUtils.isNotEmpty(plans) && (plans.get(0).getId().longValue() != id.longValue())) {
            throw new UnitedException("一个厅局只能有1个正在运行的每日巡检计划");
        }
        plan.setDisabled(false);
        this.hnInspectionPlanRepository.save(plan);
        this.addInspectionScheduleJob(plan);
    }

    @Override
    public void disable(final Long id) {
        final HnInspectionPlan plan = this.hnInspectionPlanRepository.getOne(id);
        if (plan == null) {
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND, new Object[] {id });
        }
        plan.setDisabled(true);
        this.hnInspectionPlanRepository.save(plan);
        this.addInspectionScheduleJob(plan);
    }
}
